//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension AIOps {
    // MARK: Enums

    public enum EncryptionConfigurationType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case awsOwnedKey = "AWS_OWNED_KEY"
        case customerManagedKmsKey = "CUSTOMER_MANAGED_KMS_KEY"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct CreateInvestigationGroupInput: AWSEncodableShape {
        /// Use this structure to integrate CloudWatch investigations with Amazon Q in chat applications. This structure is a string array. For the first string, specify the ARN of an Amazon SNS topic. For the array of strings, specify the ARNs of one or more Amazon Q in chat applications configurations that you want to associate with that topic. For more information about these configuration ARNs, see Getting started with Amazon Q in chat applications and Resource type defined by Amazon Web Services Chatbot.
        public let chatbotNotificationChannel: [String: [String]]?
        /// Number of sourceAccountId values that have been configured for cross-account access.
        public let crossAccountConfigurations: [CrossAccountConfiguration]?
        /// Use this structure if you want to use a customer managed KMS key to encrypt your investigation data. If you omit this parameter, CloudWatch investigations will use an Amazon Web Services key to encrypt the data. For more information, see Encryption of investigation data.
        public let encryptionConfiguration: EncryptionConfiguration?
        /// Specify true to enable CloudWatch investigations to have access to change events that are recorded by CloudTrail. The default is true.
        public let isCloudTrailEventHistoryEnabled: Bool?
        /// Provides a name for the investigation group.
        public let name: String
        /// Specify how long that investigation data is kept. For more information, see Operational investigation data retention.  If you omit this parameter, the default of 90 days is used.
        public let retentionInDays: Int64?
        /// Specify the ARN of the IAM role that CloudWatch investigations will use when it gathers investigation data. The permissions in this role determine which of your resources that CloudWatch investigations will have access to during investigations. For more information, see How to control what data Amazon Q has access to during investigations.
        public let roleArn: String
        /// Enter the existing custom tag keys for custom applications in your system. Resource tags help Amazon Q narrow the search space when it is unable to discover definite relationships between resources. For example, to discover that an Amazon ECS service depends on an Amazon RDS database, Amazon Q can discover this relationship using data sources such as X-Ray and CloudWatch Application Signals. However, if you haven't deployed these features, Amazon Q will attempt to identify possible relationships. Tag boundaries can be used to narrow the resources that will be discovered by Amazon Q in these cases. You don't need to enter tags created by myApplications or CloudFormation, because Amazon Q can automatically detect those tags.
        public let tagKeyBoundaries: [String]?
        /// A list of key-value pairs to associate with the investigation group. You can associate as many as 50 tags with an investigation group. To be able to associate tags when you create the investigation group, you must have the cloudwatch:TagResource permission. Tags can help you organize and categorize your resources. You can also use them to scope user permissions by granting a user permission to access or change only resources with certain tag values.
        public let tags: [String: String]?

        @inlinable
        public init(chatbotNotificationChannel: [String: [String]]? = nil, crossAccountConfigurations: [CrossAccountConfiguration]? = nil, encryptionConfiguration: EncryptionConfiguration? = nil, isCloudTrailEventHistoryEnabled: Bool? = nil, name: String, retentionInDays: Int64? = nil, roleArn: String, tagKeyBoundaries: [String]? = nil, tags: [String: String]? = nil) {
            self.chatbotNotificationChannel = chatbotNotificationChannel
            self.crossAccountConfigurations = crossAccountConfigurations
            self.encryptionConfiguration = encryptionConfiguration
            self.isCloudTrailEventHistoryEnabled = isCloudTrailEventHistoryEnabled
            self.name = name
            self.retentionInDays = retentionInDays
            self.roleArn = roleArn
            self.tagKeyBoundaries = tagKeyBoundaries
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.chatbotNotificationChannel?.forEach {
                try validate($0.key, name: "chatbotNotificationChannel.key", parent: name, max: 2048)
                try validate($0.key, name: "chatbotNotificationChannel.key", parent: name, min: 20)
                try validate($0.key, name: "chatbotNotificationChannel.key", parent: name, pattern: "^arn:.*$")
                try validate($0.value, name: "chatbotNotificationChannel[\"\($0.key)\"]", parent: name, max: 5)
                try validate($0.value, name: "chatbotNotificationChannel[\"\($0.key)\"]", parent: name, min: 1)
            }
            try self.crossAccountConfigurations?.forEach {
                try $0.validate(name: "\(name).crossAccountConfigurations[]")
            }
            try self.validate(self.crossAccountConfigurations, name: "crossAccountConfigurations", parent: name, max: 25)
            try self.encryptionConfiguration?.validate(name: "\(name).encryptionConfiguration")
            try self.validate(self.name, name: "name", parent: name, max: 512)
            try self.validate(self.name, name: "name", parent: name, min: 1)
            try self.validate(self.name, name: "name", parent: name, pattern: "^[\\-_A-Za-z0-9\\[\\]\\(\\)\\{\\}\\.: ]+$")
            try self.validate(self.retentionInDays, name: "retentionInDays", parent: name, max: 90)
            try self.validate(self.retentionInDays, name: "retentionInDays", parent: name, min: 7)
            try self.validate(self.roleArn, name: "roleArn", parent: name, max: 2048)
            try self.validate(self.roleArn, name: "roleArn", parent: name, min: 20)
            try self.validate(self.roleArn, name: "roleArn", parent: name, pattern: "^arn:.*$")
            try self.tagKeyBoundaries?.forEach {
                try validate($0, name: "tagKeyBoundaries[]", parent: name, max: 128)
                try validate($0, name: "tagKeyBoundaries[]", parent: name, min: 1)
                try validate($0, name: "tagKeyBoundaries[]", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+)$")
            }
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+)$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case chatbotNotificationChannel = "chatbotNotificationChannel"
            case crossAccountConfigurations = "crossAccountConfigurations"
            case encryptionConfiguration = "encryptionConfiguration"
            case isCloudTrailEventHistoryEnabled = "isCloudTrailEventHistoryEnabled"
            case name = "name"
            case retentionInDays = "retentionInDays"
            case roleArn = "roleArn"
            case tagKeyBoundaries = "tagKeyBoundaries"
            case tags = "tags"
        }
    }

    public struct CreateInvestigationGroupOutput: AWSDecodableShape {
        /// The ARN of the investigation group that you just created.
        public let arn: String?

        @inlinable
        public init(arn: String? = nil) {
            self.arn = arn
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
        }
    }

    public struct CrossAccountConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// The ARN of an existing role which will be used to do investigations on your behalf.
        public let sourceRoleArn: String?

        @inlinable
        public init(sourceRoleArn: String? = nil) {
            self.sourceRoleArn = sourceRoleArn
        }

        public func validate(name: String) throws {
            try self.validate(self.sourceRoleArn, name: "sourceRoleArn", parent: name, max: 2048)
            try self.validate(self.sourceRoleArn, name: "sourceRoleArn", parent: name, min: 20)
            try self.validate(self.sourceRoleArn, name: "sourceRoleArn", parent: name, pattern: "^arn:.*$")
        }

        private enum CodingKeys: String, CodingKey {
            case sourceRoleArn = "sourceRoleArn"
        }
    }

    public struct DeleteInvestigationGroupPolicyOutput: AWSDecodableShape {
        public init() {}
    }

    public struct DeleteInvestigationGroupPolicyRequest: AWSEncodableShape {
        /// Specify either the name or the ARN of the investigation group that you want to remove the policy from.
        public let identifier: String

        @inlinable
        public init(identifier: String) {
            self.identifier = identifier
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.identifier, key: "identifier")
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^(?:[\\-_A-Za-z0-9]{1,512}|arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):aiops:[a-zA-Z0-9-]*:[0-9]{12}:investigation-group\\/[A-Za-z0-9]{16})$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteInvestigationGroupRequest: AWSEncodableShape {
        /// Specify either the name or the ARN of the investigation group that you want to delete.
        public let identifier: String

        @inlinable
        public init(identifier: String) {
            self.identifier = identifier
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.identifier, key: "identifier")
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^(?:[\\-_A-Za-z0-9]{1,512}|arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):aiops:[a-zA-Z0-9-]*:[0-9]{12}:investigation-group\\/[A-Za-z0-9]{16})$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct EncryptionConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// If the investigation group uses a customer managed key for encryption, this field displays the ID of that key.
        public let kmsKeyId: String?
        /// Displays whether investigation data is encrypted by a customer managed key or an Amazon Web Services owned kay.
        public let type: EncryptionConfigurationType?

        @inlinable
        public init(kmsKeyId: String? = nil, type: EncryptionConfigurationType? = nil) {
            self.kmsKeyId = kmsKeyId
            self.type = type
        }

        public func validate(name: String) throws {
            try self.validate(self.kmsKeyId, name: "kmsKeyId", parent: name, max: 256)
            try self.validate(self.kmsKeyId, name: "kmsKeyId", parent: name, min: 1)
            try self.validate(self.kmsKeyId, name: "kmsKeyId", parent: name, pattern: "^arn:.*$")
        }

        private enum CodingKeys: String, CodingKey {
            case kmsKeyId = "kmsKeyId"
            case type = "type"
        }
    }

    public struct GetInvestigationGroupPolicyRequest: AWSEncodableShape {
        /// Specify either the name or the ARN of the investigation group that you want to view the policy of.
        public let identifier: String

        @inlinable
        public init(identifier: String) {
            self.identifier = identifier
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.identifier, key: "identifier")
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^(?:[\\-_A-Za-z0-9]{1,512}|arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):aiops:[a-zA-Z0-9-]*:[0-9]{12}:investigation-group\\/[A-Za-z0-9]{16})$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetInvestigationGroupPolicyResponse: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the investigation group that you want to view the policy of.
        public let investigationGroupArn: String?
        /// The policy, in JSON format.
        public let policy: String?

        @inlinable
        public init(investigationGroupArn: String? = nil, policy: String? = nil) {
            self.investigationGroupArn = investigationGroupArn
            self.policy = policy
        }

        private enum CodingKeys: String, CodingKey {
            case investigationGroupArn = "investigationGroupArn"
            case policy = "policy"
        }
    }

    public struct GetInvestigationGroupRequest: AWSEncodableShape {
        /// Specify either the name or the ARN of the investigation group that you want to view.
        public let identifier: String

        @inlinable
        public init(identifier: String) {
            self.identifier = identifier
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.identifier, key: "identifier")
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^(?:[\\-_A-Za-z0-9]{1,512}|arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):aiops:[a-zA-Z0-9-]*:[0-9]{12}:investigation-group\\/[A-Za-z0-9]{16})$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetInvestigationGroupResponse: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the investigation group.
        public let arn: String?
        /// This structure is a string array. The first string is the ARN of a Amazon SNS topic. The array of strings display the ARNs of Amazon Q in chat applications configurations that are associated with that topic. For more information about these configuration ARNs, see Getting started with Amazon Q in chat applications and Resource type defined by Amazon Web Services Chatbot.
        public let chatbotNotificationChannel: [String: [String]]?
        /// The date and time that the investigation group was created.
        public let createdAt: Date?
        /// The name of the user who created the investigation group.
        public let createdBy: String?
        /// Lists the AWSAccountId of the accounts configured for cross-account access and the results of the last scan performed on each account.
        public let crossAccountConfigurations: [CrossAccountConfiguration]?
        /// Specifies the customer managed KMS key that the investigation group uses to encrypt data, if there is one. If not, the investigation group uses an Amazon Web Services key to encrypt the data.
        public let encryptionConfiguration: EncryptionConfiguration?
        /// Specifies whether CloudWatch investigationshas access to change events that are recorded by CloudTrail.
        public let isCloudTrailEventHistoryEnabled: Bool?
        /// The date and time that the investigation group was most recently modified.
        public let lastModifiedAt: Date?
        /// The name of the user who created the investigation group.
        public let lastModifiedBy: String?
        /// The name of the investigation group.
        public let name: String?
        /// Specifies how long that investigation data is kept.
        public let retentionInDays: Int64?
        /// The ARN of the IAM role that the investigation group uses for permissions to gather data.
        public let roleArn: String?
        /// Displays the custom tag keys for custom applications in your system that you have specified in the investigation group. Resource tags help Amazon Q narrow the search space when it is unable to discover definite relationships between resources.
        public let tagKeyBoundaries: [String]?

        @inlinable
        public init(arn: String? = nil, chatbotNotificationChannel: [String: [String]]? = nil, createdAt: Date? = nil, createdBy: String? = nil, crossAccountConfigurations: [CrossAccountConfiguration]? = nil, encryptionConfiguration: EncryptionConfiguration? = nil, isCloudTrailEventHistoryEnabled: Bool? = nil, lastModifiedAt: Date? = nil, lastModifiedBy: String? = nil, name: String? = nil, retentionInDays: Int64? = nil, roleArn: String? = nil, tagKeyBoundaries: [String]? = nil) {
            self.arn = arn
            self.chatbotNotificationChannel = chatbotNotificationChannel
            self.createdAt = createdAt
            self.createdBy = createdBy
            self.crossAccountConfigurations = crossAccountConfigurations
            self.encryptionConfiguration = encryptionConfiguration
            self.isCloudTrailEventHistoryEnabled = isCloudTrailEventHistoryEnabled
            self.lastModifiedAt = lastModifiedAt
            self.lastModifiedBy = lastModifiedBy
            self.name = name
            self.retentionInDays = retentionInDays
            self.roleArn = roleArn
            self.tagKeyBoundaries = tagKeyBoundaries
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
            case chatbotNotificationChannel = "chatbotNotificationChannel"
            case createdAt = "createdAt"
            case createdBy = "createdBy"
            case crossAccountConfigurations = "crossAccountConfigurations"
            case encryptionConfiguration = "encryptionConfiguration"
            case isCloudTrailEventHistoryEnabled = "isCloudTrailEventHistoryEnabled"
            case lastModifiedAt = "lastModifiedAt"
            case lastModifiedBy = "lastModifiedBy"
            case name = "name"
            case retentionInDays = "retentionInDays"
            case roleArn = "roleArn"
            case tagKeyBoundaries = "tagKeyBoundaries"
        }
    }

    public struct ListInvestigationGroupsInput: AWSEncodableShape {
        /// The maximum number of results to return in one operation. If you omit this parameter, the default of 50 is used.
        public let maxResults: Int?
        /// Include this value, if it was returned by the previous operation, to get the next set of service operations.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.maxResults, key: "maxResults")
            request.encodeQuery(self.nextToken, key: "nextToken")
        }

        public func validate(name: String) throws {
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 2048)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListInvestigationGroupsModel: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the investigation group.
        public let arn: String?
        /// The name of the investigation group.
        public let name: String?

        @inlinable
        public init(arn: String? = nil, name: String? = nil) {
            self.arn = arn
            self.name = name
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
            case name = "name"
        }
    }

    public struct ListInvestigationGroupsOutput: AWSDecodableShape {
        /// An array of structures, where each structure contains the information about one investigation group in the account.
        public let investigationGroups: [ListInvestigationGroupsModel]?
        /// Include this value in your next use of this operation to get the next set of service operations.
        public let nextToken: String?

        @inlinable
        public init(investigationGroups: [ListInvestigationGroupsModel]? = nil, nextToken: String? = nil) {
            self.investigationGroups = investigationGroups
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case investigationGroups = "investigationGroups"
            case nextToken = "nextToken"
        }
    }

    public struct ListTagsForResourceOutput: AWSDecodableShape {
        /// The list of tag keys and values associated with the resource you specified.
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        /// The ARN of the CloudWatch investigations resource that you want to view tags for. You can use the ListInvestigationGroups operation to find the ARNs of investigation groups. The ARN format for an investigation group is arn:aws:aiops:Region:account-id:investigation-group:investigation-group-id .
        public let resourceArn: String

        @inlinable
        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct PutInvestigationGroupPolicyRequest: AWSEncodableShape {
        /// Specify either the name or the ARN of the investigation group that you want to assign the policy to.
        public let identifier: String
        /// The policy, in JSON format.
        public let policy: String

        @inlinable
        public init(identifier: String, policy: String) {
            self.identifier = identifier
            self.policy = policy
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.identifier, key: "identifier")
            try container.encode(self.policy, forKey: .policy)
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^(?:[\\-_A-Za-z0-9]{1,512}|arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):aiops:[a-zA-Z0-9-]*:[0-9]{12}:investigation-group\\/[A-Za-z0-9]{16})$")
            try self.validate(self.policy, name: "policy", parent: name, max: 32768)
            try self.validate(self.policy, name: "policy", parent: name, min: 1)
            try self.validate(self.policy, name: "policy", parent: name, pattern: "^[\\u0009\\u000A\\u000D\\u0020-\\u00FF]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case policy = "policy"
        }
    }

    public struct PutInvestigationGroupPolicyResponse: AWSDecodableShape {
        /// The ARN of the investigation group that will use this policy.
        public let investigationGroupArn: String?

        @inlinable
        public init(investigationGroupArn: String? = nil) {
            self.investigationGroupArn = investigationGroupArn
        }

        private enum CodingKeys: String, CodingKey {
            case investigationGroupArn = "investigationGroupArn"
        }
    }

    public struct ServiceQuotaExceededException: AWSErrorShape {
        public let message: String?
        /// This quota that was exceeded.
        public let quotaCode: String?
        /// The resource that caused the quota exception.
        public let resourceId: String?
        /// The type of resource that caused the quota exception.
        public let resourceType: String?
        /// This name of the service associated with the error.
        public let serviceCode: String?

        @inlinable
        public init(message: String? = nil, quotaCode: String? = nil, resourceId: String? = nil, resourceType: String? = nil, serviceCode: String? = nil) {
            self.message = message
            self.quotaCode = quotaCode
            self.resourceId = resourceId
            self.resourceType = resourceType
            self.serviceCode = serviceCode
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case quotaCode = "quotaCode"
            case resourceId = "resourceId"
            case resourceType = "resourceType"
            case serviceCode = "serviceCode"
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the resource that you want to apply the tags to. You can use the ListInvestigationGroups operation to find the ARNs of investigation groups.
        public let resourceArn: String
        /// The list of key-value pairs to associate with the resource.
        public let tags: [String: String]

        @inlinable
        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
            try container.encode(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+)$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the resource that you want to remove the tags from. You can use the ListInvestigationGroups operation to find the ARNs of investigation groups.
        public let resourceArn: String
        /// The list of tag keys to remove from the resource.
        public let tagKeys: [String]

        @inlinable
        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
            request.encodeQuery(self.tagKeys, key: "tagKeys")
        }

        public func validate(name: String) throws {
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
                try validate($0, name: "tagKeys[]", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+)$")
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 50)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateInvestigationGroupOutput: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateInvestigationGroupRequest: AWSEncodableShape {
        /// Use this structure to integrate CloudWatch investigations with Amazon Q in chat applications. This structure is a string array. For the first string, specify the ARN of an Amazon SNS topic. For the array of strings, specify the ARNs of one or more Amazon Q in chat applications configurations that you want to associate with that topic. For more information about these configuration ARNs, see Getting started with Amazon Q in chat applications and Resource type defined by Amazon Web Services Chatbot.
        public let chatbotNotificationChannel: [String: [String]]?
        /// Used to configure cross-account access for an investigation group. It allows the investigation group to access resources in other accounts.
        public let crossAccountConfigurations: [CrossAccountConfiguration]?
        /// Use this structure if you want to use a customer managed KMS key to encrypt your investigation data. If you omit this parameter, CloudWatch investigations will use an Amazon Web Services key to encrypt the data. For more information, see Encryption of investigation data.
        public let encryptionConfiguration: EncryptionConfiguration?
        /// Specify either the name or the ARN of the investigation group that you want to modify.
        public let identifier: String
        /// Specify true to enable CloudWatch investigations to have access to change events that are recorded by CloudTrail. The default is true.
        public let isCloudTrailEventHistoryEnabled: Bool?
        /// Specify this field if you want to change the IAM role that CloudWatch investigations will use when it gathers investigation data. To do so, specify the ARN of the new role. The permissions in this role determine which of your resources that CloudWatch investigations will have access to during investigations. For more information, see EHow to control what data Amazon Q has access to during investigations.
        public let roleArn: String?
        /// Enter the existing custom tag keys for custom applications in your system. Resource tags help Amazon Q narrow the search space when it is unable to discover definite relationships between resources. For example, to discover that an Amazon ECS service depends on an Amazon RDS database, Amazon Q can discover this relationship using data sources such as X-Ray and CloudWatch Application Signals. However, if you haven't deployed these features, Amazon Q will attempt to identify possible relationships. Tag boundaries can be used to narrow the resources that will be discovered by Amazon Q in these cases. You don't need to enter tags created by myApplications or CloudFormation, because Amazon Q can automatically detect those tags.
        public let tagKeyBoundaries: [String]?

        @inlinable
        public init(chatbotNotificationChannel: [String: [String]]? = nil, crossAccountConfigurations: [CrossAccountConfiguration]? = nil, encryptionConfiguration: EncryptionConfiguration? = nil, identifier: String, isCloudTrailEventHistoryEnabled: Bool? = nil, roleArn: String? = nil, tagKeyBoundaries: [String]? = nil) {
            self.chatbotNotificationChannel = chatbotNotificationChannel
            self.crossAccountConfigurations = crossAccountConfigurations
            self.encryptionConfiguration = encryptionConfiguration
            self.identifier = identifier
            self.isCloudTrailEventHistoryEnabled = isCloudTrailEventHistoryEnabled
            self.roleArn = roleArn
            self.tagKeyBoundaries = tagKeyBoundaries
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encodeIfPresent(self.chatbotNotificationChannel, forKey: .chatbotNotificationChannel)
            try container.encodeIfPresent(self.crossAccountConfigurations, forKey: .crossAccountConfigurations)
            try container.encodeIfPresent(self.encryptionConfiguration, forKey: .encryptionConfiguration)
            request.encodePath(self.identifier, key: "identifier")
            try container.encodeIfPresent(self.isCloudTrailEventHistoryEnabled, forKey: .isCloudTrailEventHistoryEnabled)
            try container.encodeIfPresent(self.roleArn, forKey: .roleArn)
            try container.encodeIfPresent(self.tagKeyBoundaries, forKey: .tagKeyBoundaries)
        }

        public func validate(name: String) throws {
            try self.chatbotNotificationChannel?.forEach {
                try validate($0.key, name: "chatbotNotificationChannel.key", parent: name, max: 2048)
                try validate($0.key, name: "chatbotNotificationChannel.key", parent: name, min: 20)
                try validate($0.key, name: "chatbotNotificationChannel.key", parent: name, pattern: "^arn:.*$")
                try validate($0.value, name: "chatbotNotificationChannel[\"\($0.key)\"]", parent: name, max: 5)
                try validate($0.value, name: "chatbotNotificationChannel[\"\($0.key)\"]", parent: name, min: 1)
            }
            try self.crossAccountConfigurations?.forEach {
                try $0.validate(name: "\(name).crossAccountConfigurations[]")
            }
            try self.validate(self.crossAccountConfigurations, name: "crossAccountConfigurations", parent: name, max: 25)
            try self.encryptionConfiguration?.validate(name: "\(name).encryptionConfiguration")
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^(?:[\\-_A-Za-z0-9]{1,512}|arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):aiops:[a-zA-Z0-9-]*:[0-9]{12}:investigation-group\\/[A-Za-z0-9]{16})$")
            try self.validate(self.roleArn, name: "roleArn", parent: name, max: 2048)
            try self.validate(self.roleArn, name: "roleArn", parent: name, min: 20)
            try self.validate(self.roleArn, name: "roleArn", parent: name, pattern: "^arn:.*$")
            try self.tagKeyBoundaries?.forEach {
                try validate($0, name: "tagKeyBoundaries[]", parent: name, max: 128)
                try validate($0, name: "tagKeyBoundaries[]", parent: name, min: 1)
                try validate($0, name: "tagKeyBoundaries[]", parent: name, pattern: "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+)$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case chatbotNotificationChannel = "chatbotNotificationChannel"
            case crossAccountConfigurations = "crossAccountConfigurations"
            case encryptionConfiguration = "encryptionConfiguration"
            case isCloudTrailEventHistoryEnabled = "isCloudTrailEventHistoryEnabled"
            case roleArn = "roleArn"
            case tagKeyBoundaries = "tagKeyBoundaries"
        }
    }
}

// MARK: - Errors

/// Error enum for AIOps
public struct AIOpsErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case conflictException = "ConflictException"
        case forbiddenException = "ForbiddenException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case throttlingException = "ThrottlingException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize AIOps
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// You don't have sufficient permissions to perform this action.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// This operation couldn't be completed because of a conflict in resource states.
    public static var conflictException: Self { .init(.conflictException) }
    /// Access id denied for this operation, or this operation is not valid for the specified resource.
    public static var forbiddenException: Self { .init(.forbiddenException) }
    /// An internal server error occurred. You can try again later.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The specified resource doesn't exist.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// This request exceeds a service quota.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The request was throttled because of quota limits. You can try again later.
    public static var throttlingException: Self { .init(.throttlingException) }
    /// This operation or its parameters aren't formatted correctly.
    public static var validationException: Self { .init(.validationException) }
}

extension AIOpsErrorType: AWSServiceErrorType {
    public static let errorCodeMap: [String: AWSErrorShape.Type] = [
        "ServiceQuotaExceededException": AIOps.ServiceQuotaExceededException.self
    ]
}

extension AIOpsErrorType: Equatable {
    public static func == (lhs: AIOpsErrorType, rhs: AIOpsErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension AIOpsErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
